import os
import socket
from typing import Tuple

from lucommon.logger import lu_logger

import agent
from async_task.services import AsyncTask
from deploy.models import Cluster, ClusterStatusEnum
from utils import concurrence_requests


def check_agent_status(ip_list, timeout=5):
    if os.getenv("ENV") != "PROD":
        lu_logger.info("skip agent check")
        return []
    request_infos = {
        str(ip): {
            "url": "http://{}:{}{}".format(ip, agent.AGENT_PORT, agent.READY_CHECK),
            "method": "GET",
            "timeout": timeout
        }
        for ip in ip_list
    }
    response_map = concurrence_requests(request_infos)
    err_ips_map = {}
    for ip, result in response_map.items():
        if result["error"]:
            err_ips_map[ip] = result["error"]
            continue
        if result["status"] != 200:
            err_ips_map[ip] = result["body"]

    return err_ips_map


def check_concurrence_result(concurrence_result):
    for req_id, res in concurrence_result.items():
        if res["status"] != 200:
            return False

    return True


def check_port(ip, port):
    if os.getenv("ENV") != "PROD":
        lu_logger.info("skip agent check")
        return True
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(3)

    try:
        result = sock.connect_ex((str(ip), int(port)))
        if result == 0:
            sock.close()
            return True

    except Exception as e:
        lu_logger.error("check port error: {}:{} {}".format(ip, port, str(e)))

    sock.close()
    return False


class AsyncTaskFinishCreateCluster(AsyncTask):
    def task_impl(self, cluster: Cluster) -> Tuple[int, any]:
        cluster.status = ClusterStatusEnum.DONE
        cluster.save()
        return 0, ""
